#include "console_thread.h"
#include <QDebug>
#include <QDateTime>

static QString get_time(void)
{
	QDateTime time = QDateTime::currentDateTime();
	QString st = time.toString("[yyyy-MM-dd dd:mm:ss.zzz] ");
	return st;
}

Console_thread::Console_thread(QString log_file,QObject *parent) : 
	QThread(parent),
	log_filename(log_file)
{
	
	thread_stop = false;

	con_sem = new QSemaphore(0);
}

Console_thread::~Console_thread()
{
	file->close();

	delete datas;
	delete file;
}


void Console_thread::Read_Data()
{
	QByteArray  buf;

	buf = port->readAll();

	if(buf.isEmpty()){
		//qDebug() << "buf is Emppty"<<endl;
		return;
	}

	qDebug() << buf << endl;
	QString str(buf);
	QByteArray line;

	receive_data += buf;

	while(1){
		int end = receive_data.indexOf("\n");
		if(end == -1){
			break;
		}
		QString ctime = get_time();
		QString sline;
		//ui->textEdit->insertPlainText(ctime);
		qDebug() << "recv line"<<endl;
		emit recv_data(ctime);
		sline.append(ctime);
		line = receive_data.mid(0,end);

		if(line[line.length()-2] == '\r'){
			line.remove(line.length()-2,1);
		}
		receive_data = receive_data.mid(end+1);

		while(1){
			int st = line.indexOf("\033[");
			if(st != -1){
				QByteArray s1 = line.mid(0,st);
				sline.append(s1);

				emit recv_data(s1);
				int e = line.indexOf("m",st);
				QByteArray colorp = line.mid(st+2,e-2);

				int e2 = colorp.indexOf(";");
				if(e2 != -1){
					QByteArray colorp1 = colorp.mid(0,e2);
					emit style_change(colorp1.toInt());

					colorp = colorp.mid(e2+1);
					emit style_change(colorp.toInt());
				}else{
					emit style_change(colorp.toInt());
				}

				line = line.mid(e+1);

			}else{
				sline.append(line);
				emit recv_data(line);
				break;
			}
		}
		check_line(sline);
		*datas << sline;
	}
}

void Console_thread::run()
{
	qDebug() << "Console thread run baudrate:"<<baudrate << endl;
	
	port = new QSerialPort();
	port->setBaudRate(baudrate);
	port->setStopBits(QSerialPort::OneStop);
	port->setParity(QSerialPort::NoParity);
	port->setPortName(port_name);
	if(port->open(QIODevice::ReadWrite)){
		qDebug()<<"Open serial port "<<port->portName()<<" successful";
	}else{
		qDebug()<<"Open serial port "<<port->portName()<<" failed";
		return;
	}

	if(log_filename.length() == 0){
		QDateTime time = QDateTime::currentDateTime();
		QString st = time.toString("yyyy-MM-dd_hh-mm-ss");
		log_filename = port->portName() + st + ".log";
	}
	file = new QFile(log_filename);
	if(file->exists()){
		file->open(QIODevice::Append | QIODevice::Text);
	}else{
		file->open(QIODevice::WriteOnly | QIODevice::Text);
	}
	datas = new QDataStream(file);

	while(1){
		if(thread_stop){
			break;
		}
		if(!send_list.isEmpty()){
			QByteArray cmd = send_list.takeFirst();
			send_cmd(cmd);
		}
		//qDebug() << "Read_Data"<<endl;
		Read_Data();
	}
	thread_stop = false;

	port->close();
	delete port;
	delete file;
	delete datas;
}

void Console_thread::thread_quit()
{
	thread_stop = true;
}

void Console_thread::check_line(QString line)
{
	int i;
	rule_mutex.lock();
	for(i = 0; i < checklist.size(); i++){
		int pos = checklist[i]->indexIn(line);
		if(pos != -1){
			rule_result = checklist[i]->cap();
			con_sem->release();
			break;
		}
	}
	rule_mutex.unlock();
}

void *Console_thread::add_check_rule(QString rule)
{
	QRegExp *rx = new QRegExp(rule);
	checklist.append(rx);

	return rx;
}

void Console_thread::delete_rule(void *rule)
{
	checklist.removeOne((QRegExp*)rule);
}

QString Console_thread::wait_string(QString str, int timeout_ms)
{
	rule_mutex.lock();
	void *rule = add_check_rule(str);
	rule_mutex.unlock();
	int ret = con_sem->tryAcquire(1, timeout_ms);
	if(!ret){
		return NULL;
	}
	rule_mutex.lock();
	delete_rule(rule);
	rule_mutex.unlock();
	return rule_result;
}

int Console_thread::send_cmd(QByteArray cmd)
{
	char *buf = cmd.data();
	int ret = port->write(buf,cmd.length());
	bool flush = port->flush();
	qDebug() << "ret:" << ret <<"flush:"<<flush<< endl;
	return ret;
}

int Console_thread::send(QByteArray cmd)
{
	QByteArray str(cmd);
	send_list.append(str);
	
	qDebug()<<"send: " << cmd << endl;
	return 0;
}

void Console_thread::port_set(QString portname, int rate)
{
	port_name = portname;
	baudrate = rate;
}
